{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 01 Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 02 Repository Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Step 1: Clone the repository"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cloning into 'codecrafters-redis-cpp'...\n"
     ]
    }
   ],
   "source": [
    "! git clone https://git.codecrafters.io/bdac2ec379dd3cb6 codecrafters-redis-cpp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cd codecrafters-redis-cpp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Step 2: Push an empty commit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git commit --allow-empty -m 'test'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git push origin master"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 03 Bind to a port"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Redis servers communicate over TCP, a protocol that enables reliable data exchange between clients and servers. In this stage, you’ll implement a TCP server that listens on port 6379, just like the real Redis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Step 1: Uncomment code in src/main.cpp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- \"02_Repository Setup/main.cpp\"\t2025-10-14 04:08:56.521636400 +0800\n",
      "+++ \"03_Bind to a port/main.cpp\"\t2025-10-14 04:09:21.898810300 +0800\n",
      "@@ -52,10 +52,10 @@\n",
      " \n",
      "   // Uncomment this block to pass the first stage\n",
      "   // \n",
      "-  // accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len);\n",
      "-  // std::cout << \"Client connected\\n\";\n",
      "+  accept(server_fd, (struct sockaddr *) &client_addr, (socklen_t *) &client_addr_len);\n",
      "+  std::cout << \"Client connected\\n\";\n",
      "   // \n",
      "-  // close(server_fd);\n",
      "+  close(server_fd);\n",
      " \n",
      "   return 0;\n",
      " }\n"
     ]
    }
   ],
   "source": [
    "! diff -u '02_Repository Setup'/main.cpp '03_Bind to a port'/main.cpp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Step 2: Git push to submit your changes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git commit -am \"[any message]\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git push origin master"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 04 Respond to PING "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Implement solution\n",
    "\n",
    "- [main.cpp](./04_Respond%20to%20PING/main.cpp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Run tests"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git add ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git commit --allow-empty -m \"[any message]\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! git push origin master"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Your Task\n",
    "\n",
    "In this stage, you'll implement support for the [PING](https://redis.io/commands/ping) command.\n",
    "\n",
    "### TCP (Transmission Control Protocol)\n",
    "\n",
    "[TCP](https://en.wikipedia.org/wiki/Transmission_Control_Protocol) is the underlying protocol used by protocols like HTTP, SSH, and others you're probably familiar with. Redis also uses TCP for communication between its clients and servers.\n",
    "\n",
    "Don't worry if you're unfamiliar with the TCP protocol, or what Redis clients & servers are. You'll learn more about this in the next stages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Redis Commands\n",
    "\n",
    "Redis clients communicate with Redis servers by sending [commands](https://redis.io/commands/). For each command, a Redis server sends a response back to the client.\n",
    "\n",
    "For example:\n",
    "\n",
    "```bash\n",
    "$ redis-cli SET name Alice\n",
    "OK\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "OK\n"
     ]
    }
   ],
   "source": [
    "! redis-cli SET name Alice"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here, the client sends a [`SET`](https://redis.io/docs/latest/commands/set/) command to store the key `name` with the value `Alice`. The server responds with `OK`, confirming that the action was successful.\n",
    "\n",
    "Both commands and responses are encoded using the [Redis serialization protocol (RESP)](https://redis.io/docs/latest/develop/reference/protocol-spec/). We'll learn more about this in later stages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The `PING` Command\n",
    "\n",
    "[PING](https://redis.io/commands/ping/) is one of the simplest Redis commands. It's used to check whether a Redis server is healthy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PONG\n"
     ]
    }
   ],
   "source": [
    "! redis-cli PING"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The response for the `PING` command is `+PONG\\r\\n`. This is the string \"PONG\" encoded as a [RESP simple string](https://redis.io/docs/latest/develop/reference/protocol-spec/#simple-strings).\n",
    "\n",
    "In this stage, you can ignore the client input and simply hardcode `+PONG\\r\\n` as a response. We'll get to parsing the client's input in later stages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tests\n",
    "\n",
    "The tester will execute your program like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cd '04_Respond to PING' && g++ -O3 main.cpp -o redis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cd '04_Respond to PING' && $ ./redis\n",
    "Failed to bind to port 6379"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! sudo lsof -i :6379\n",
    "COMMAND      PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME\n",
    "redis-ser 115741 redis    6u  IPv4 1417473      0t0  TCP localhost:redis (LISTEN)\n",
    "redis-ser 115741 redis    7u  IPv6 1417474      0t0  TCP ip6-localhost:redis (LISTEN)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! redis-cli -p 6379 shutdown "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! sudo systemctl stop redis-server"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! cd '04_Respond to PING' &&  ./redis\n",
    "Waiting for a client to connect...\n",
    "Logs from your program will appear here!\n",
    "Client connected"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It'll then send a `PING` command to your server."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PONG\n"
     ]
    }
   ],
   "source": [
    "! redis-cli PING"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Your server should respond with `+PONG\\r\\n`, which is `PONG` encoded as a [simple string](https://redis.io/docs/latest/develop/reference/protocol-spec/#simple-strings)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Notes\n",
    "\n",
    "- You can ignore the data that the tester sends you for this stage. We'll get to parsing client input in later stages. For now, you can just hardcode `+PONG\\r\\n` as the response.\n",
    "- You can also ignore handling multiple clients and handling multiple PING commands in this stage—we'll get to that in later stages.\n",
    "- The exact bytes your program will receive won't just be `PING`. Instead, you'll receive something like this: `*1\\r\\n$4\\r\\nPING\\r\\n`, which is the Redis protocol encoding of the `PING` command. We'll learn more about this in later stages."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 05 Respond to multiple PINGs"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Your Task\n",
    "\n",
    "In this stage, you'll respond to multiple [PING](https://redis.io/commands/ping) commands sent by the same connection."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Handling Multiple Commands\n",
    "\n",
    "A Redis server starts to listen for the next command as soon as it's done responding to the previous one. This allows Redis clients to send multiple commands using the same connection.\n",
    "\n",
    "For this stage, your server should run a loop that continuously reads commands and sends responses back through the same connection. Since we're only dealing with the `PING` command for now, your program can run a loop that reads input and responds with `+PONG\\r\\n`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tests\n",
    "\n",
    "The tester will execute your program like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! ./your_program.sh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Could not connect to Redis at 127.0.0.1:6379: Connection refused\n",
      "Could not connect to Redis at 127.0.0.1:6379: Connection refused\n",
      "Could not connect to Redis at 127.0.0.1:6379: Connection refused\n"
     ]
    }
   ],
   "source": [
    "! echo -e \"PING\\nPING\" | redis-cli"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "C++17",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
